/* eslint-disable @typescript-eslint/no-explicit-any */
// import { useMock } from '@/mock/mock';
import axios, { AxiosRequestConfig } from 'axios';

/** 不再兼容非标准的数据结构 */
export declare type AjaxPromise<R> = Promise<R>;
/** 非标准包裹 */
export declare type NonStandardAjaxPromise<R> = Promise<{
  code?: number;
  msg?: string;
  data: R;
}>;
export interface ExtraFetchParams {
  /** extra data for extends */
  extra?: any;
  /** 扩展请求头 */
  headers?: any;
  /** cancel request */
  cancel?: Promise<string | undefined>;
}
export interface WrappedFetchParams extends ExtraFetchParams {
  /** http method */
  method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'PATCH' | 'HEAD';
  url: string;
  /** post json data */
  data?: any;
  /** post form data */
  form?: any;
  /** query data */
  query?: any;
  /** header */
  header?: any;
  /** path data */
  path?: any;
}

export const fetch = axios.create({
  timeout: 60000,
  withCredentials: false,
});

fetch.interceptors.request.use(async (config) => {
  // mock
  // if (config.url && useMock && (await useMock(config.url))) {
  //   config.url = '/mock' + config.url;
  //   console.log('[api] use mock: ' + config.url);
  // }

  // 添加签名
  // const secureHeaders = signApi();
  // config.headers = {
  //   ...config.headers,
  //   ...secureHeaders,
  // };

  return config;
});

// class WrappedFetch
const ajax = {
  /** ajax 方法 */
  ajax(
    param: WrappedFetchParams,
    path?: string,
    basePath?: string,
  ): Promise<any> {
    const { method, url, data, form, query, header, extra, cancel, headers } =
      param;

    let config: AxiosRequestConfig = {
      ...extra,
      method: method.toLowerCase(),
      headers: { ...headers, ...header },
    };

    // json
    if (data) {
      config = {
        ...config,
        headers: {
          // 可覆盖
          'Content-Type': 'application/json',
          ...config.headers,
        },
        data: data,
      };
    }

    // form
    if (form) {
      config = {
        ...config,
        data: form,
      };
    }

    // 下载
    if (extra?.download) {
      config = {
        ...config,
        responseType: 'blob',
      };
    }

    return fetch
      .request({
        ...config,
        url: url,
        params: query,
      })
      .then((response) => {
        if (response.status !== 200) {
          throw new Error(`${response.statusText}`);
        }

        // 下载
        if (extra?.download) {
          // 包装成文件

          // 获取文件名
          let filename = '';
          // content-disposition: "attachment; filename=%E7%8F%AD%E7%BA%A7%E8%AF%BE%E7%A8%8B%E8%A1%A8.xlsx"
          const contentDisposition = String(
            response.headers['content-disposition'] ?? '',
          );
          for (const part of contentDisposition.split(/;(?: *)/)) {
            const [k, v] = part.split('=');
            // 优先用 filename*，其次 filename
            if (k === 'filename*') {
              filename = v;
              break;
            } else if (k === 'filename') {
              filename = v;
            }
          }
          // decode url-encoded
          filename = decodeURIComponent(filename);

          const file = new File([response.data], filename, {
            type: 'text/plain',
          });

          return file;
        }

        // json
        return response.data;
      });
  },
};

export default ajax;
